# -*- coding: UTF-8 -*- 

import os, re, sys, time, shutil
from invoiceVo import InvoiceFileInfo
# sys.path.append('..')
import PaddleOCR
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# from paddleocr import PaddleOCR
from decimal import Decimal, getcontext

getcontext().prec = 5

# 发票所在文件夹位置
directory_path = r'./imgs'
duplicate_file_save_path = r'./imgs/toDelete'

# Paddleocr目前支持的多语言语种可以通过修改lang参数进行切换
# 例如`ch`, `en`, `fr`, `german`, `korean`, `japan`
ocr = PaddleOCR(use_angle_cls=False, lang="ch")  # need to run only once to download and load model into memory

total = Decimal(0.00)
totalNumInLineRegex = r'[（(]小写[）)][¥￥]\d+\. ?\d+'
totalNumInNeighborLineRegex = r'[（(]小写[）)][¥￥]?'
numSplitRegex = re.compile(r" ?[:：] ?")
numCNRegex = re.compile(r'[¥￥]\d+\. ?\d+')
numYSplitRegex = re.compile(r" ?[¥￥] ?")
noneNumCharsRegex = re.compile(r"[¥￥ ]")

allInvType=set()
allNumStr=set()
eInvoiceTypeSet=set((
'电子发票（普通发票）',
'电子发发（普通发票）',
'电子发票普通发票）',
'电子发票普通发票)',
'电子发票（普通发票)',
'电子发票（晋通发票）',
'电子发票(普通发票)',
'电子发票统（普通发票）',
'电子发发票普通发票）',
'电子发发票（普通发票）',
'电子发普通发票）',
'电子发发票普通',
'电子发票(晋通发票）'
))



def getNumVal(numStr):
    strConverted = numStr.strip().replace(" ", "").replace("¥", "").replace("￥", "")
    # print("strConverted num:", strConverted)
    if re.compile(r"\d+\.?\d*").match(strConverted):
        return Decimal(strConverted)
    raise Exception("numStr '" +numStr+ "' is not digit")


def calcTotalAmount(img_path, result):
    global total
    global totalNumInLineRegex
    totalOne = Decimal(-1)
    for idx in range(len(result)):
        res = result[idx]
        for lineIdx in range(len(res)):
            line = res[lineIdx]
            # print(line);
            if len(line) == 0:
                continue
            totalStr = line[1][0]
            reliable = line[1][1]
            if(re.match(totalNumInLineRegex,totalStr) != None):
                print(img_path, totalStr)
                totalOne = getNumVal(totalStr[5:])
                if(reliable < 0.85):
                    print("get unReliable item:", reliable)
                break
            elif(re.fullmatch(totalNumInNeighborLineRegex,totalStr) != None):
                nextIdex = lineIdx + 1
                line = res[nextIdex]
                
                if len(line) == 0:
                    continue
                totalStr = line[1][0]
                reliable = line[1][1]
                if(reliable < 0.85):
                    print("get unReliable item:", reliable)
                totalOne = getNumVal(totalStr[1:])
                print(img_path, totalStr)
                break
    if totalOne - Decimal(-1) == 0:
        print(img_path, "not find total")
        # print(result)
        print("=====================================")
    else:
        total = totalOne + total
    return totalOne


def getInvoiceType(result):
    if( len(result) == 0):
        return ""
    if( len(result[0]) == 0):
        return ""
    type = result[0][0][1][0]
    if(len(type) < 4):
        type = type + result[0][1][1][0]
    print("type:", type)
    global allInvType
    allInvType.add(type)

    if(type in eInvoiceTypeSet):
        return "电子发票（普通发票)"
    
    return type

def getInvoiceNum(result, startRow=1):
    if(startRow >= len(result[0])):
        return ""
    numStr = result[0][startRow][1][0]
    if(numStr.find("号码")==-1):
        startRow = startRow + 1
        return getInvoiceNum(result, startRow)
    if(len(numStr) < 13):
        startRow = startRow + 1
        numStr = numStr + result[0][startRow][1][0]
    

    print("numStr:", numStr)
    
    numStrArr = numSplitRegex.split(numStr)
    if(len(numStrArr) < 2):
        return ""
    numStrArr = numSplitRegex.split(numStr)
    numName = numStrArr[0]
    numVal = numStrArr[1]
    global allNumStr
    allNumStr.add(numName)

    # if(type in eInvoiceTypeSet):
    #     return "电子发票（普通发票)"
    
    return numVal


def getInvoiceAmountExcludingTax(result, startRow=22):
    global numYSplitRegex
    if((startRow+2) >= len(result[0])):
        return -1
    numStr = result[0][startRow][1][0].strip()
    startRowNext = startRow + 1
    numStrNext = result[0][startRowNext][1][0].strip()
    
    amountExcludingTaxRow = startRowNext + 1
    amountExcludingTax = result[0][amountExcludingTaxRow][1][0]
    if(((numStr == "合" and numStrNext == "计") or (numStr == "计" and numStrNext == "合"))
       and numCNRegex.match(amountExcludingTax)):
            return getNumVal(numYSplitRegex.split(amountExcludingTax.strip())[1])
    elif((numStr == "计" or numStr == "合")):
        if numCNRegex.match(numStrNext):
            return getNumVal(numYSplitRegex.split(numStrNext.strip())[1])
        before1Indx = startRow - 1
        before2Indx = startRow - 2
        numStrBefore1 = result[0][before1Indx][1][0].strip()
        numStrBefore2 = result[0][before2Indx][1][0].strip()
        if numCNRegex.match(numStrBefore1) and numCNRegex.match(numStrBefore2):
            return getNumVal(numYSplitRegex.split(numStrBefore1.strip())[1])
        else:
            return -1
    else:
        startRow = startRow + 1
        return getInvoiceAmountExcludingTax(result, startRow)
    return -1

def orcAndCaclInvoice(
    img_path: str,
    fileName: str = None,
): 
    # img_path = './imgs/1726905907393_100.JPG'
    result = ocr.ocr(
            img_path, 
            det=True,
            rec=True,
            cls=False,
            bin=False,
            inv=False,
            alpha_color=(0, 0, 0),
            slice={})
    # print(result)
    
    text = ''.join([line[1][0] for line in result[0]])
    # print(text)


    iv = InvoiceFileInfo()
    # iv.buyer_name = buyer_name
    # iv.buyer_tax_number = buyer_tax_number
    # iv.seller_name = seller_name
    # iv.seller_tax_number = seller_tax_number
    # iv.invoice_code = invoice_code
    # iv.invoice_date = invoice_date
    # iv.tax_amount = tax_amount
    
    # amountExcludingTax = getInvoiceAmountExcludingTax(result)
    # print("amountExcludingTax:", amountExcludingTax)
    # iv.amount_excluding_tax = amountExcludingTax

    #iv.invoice_type = getInvoiceType(result)
    iv.invoice_number = getInvoiceNum(result)

    iv.total_amount = calcTotalAmount(img_path, result)

    # iv.invoice_remark = invoice_remark
    iv.file_path = fileName
    return iv
    

    
def traverse_directory(directory_path):
    print("start traverse directory:", directory_path)
    count = 0
    
    resInvoiceList = []
    # for root, dirs, files in os.walk(directory_path):
    #     for file in files:
    #         file_path = os.path.join(root, file)
    #         startTime = time.time();

    #         count = count + 1
    #         # resInvoiceList.append(orcAndCaclInvoice(file_path))

    #         print("finish calc file:", file_path, " cost:", time.time()-startTime)


    for fileName in os.listdir(directory_path):
        file_path = os.path.join(directory_path, fileName)
        if not os.path.isfile(file_path):
            continue
        startTime = time.time();

        count = count + 1
        resInvoiceList.append(orcAndCaclInvoice(file_path, fileName))

        print("finish calc file:", file_path, " cost:", time.time()-startTime)
    # print("total files count:", count)
    resInvoiceList.sort(key=lambda x: x.invoice_number, reverse=True)
    mapFilter = {}
    filesToDelete = []
    for item in resInvoiceList:
        print(item.invoice_number, '\t', item.file_path, '\t', item.total_amount)
        if(item.file_path != None and item.file_path != "" and item.invoice_number != None and item.invoice_number != ""):
            if(mapFilter[item.invoice_number] == None):
                mapFilter[item.invoice_number] = item
            else:
                filesToDelete.append(item.file_path)
                shutil.move(os.path.join(directory_path, item.file_path), os.path.join(duplicate_file_save_path, item.file_path))
    # print("total rec res:", resInvoiceList)

    # global allInvType
    # print(allInvType)

    global allNumStr
    print(allNumStr)

traverse_directory(directory_path)

# orcAndCaclInvoice("C:/Users/zli113/Documents/personal/PaddleOCR/imgs\\mmexport1724765085256.jpg")


print("total: " , total)